package com.suxin.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * @author Tang
 * @classname ZipFile
 * @description [ 压缩 | 解压缩 ]
 * @date 2021/6/24 10:06
 */
public class ZipFileUtils {

    public static void main(String[] args) throws Exception {
        File file1 = new File("C:\\Users\\ASUS\\Desktop\\test");
        File file2 = new File("C:\\Users\\ASUS\\Desktop\\test.zip");
        zip(file1,file2);
    }

    /**
     * 压缩文件
     * @param fileDirectory 要压缩的文件目录
     * @param fileZip 需要产生的zip文件
     * @throws Exception
     */
    public static void zip(File fileDirectory,File fileZip) throws Exception {
        FileOutputStream fileOutputStream = new FileOutputStream(fileZip);
        ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
        compression(fileDirectory,"",zipOutputStream);
        zipOutputStream.close();
    }

    /**
     * 压缩文件
     * @param fileDirectory 目录
     * @param basePath 路径
     * @param zipOutputStream zip 流
     */
    private static void compression(File fileDirectory, String basePath,ZipOutputStream zipOutputStream) {
        File[] files = fileDirectory.listFiles();
        Arrays.stream(files).forEach(file -> {
            try {
                if (file.isDirectory()) {
                    compression(file, basePath + file.getName() + File.separator,zipOutputStream);
                    return;
                }
                System.out.println(String.format("压缩了%s文件...", file.getName()));
                FileInputStream fileInputStream = new FileInputStream(file);
                zipOutputStream.putNextEntry(new ZipEntry(basePath + file.getName()));
                fileInputStream.getChannel().transferTo(0, file.length(), Channels.newChannel(zipOutputStream));
                fileInputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 解压到指定目录
     * @param fileDirectory 目录
     * @param fileZip 要压缩的文件
     * @throws Exception
     */
    public static void unZip(File fileDirectory, File fileZip) throws Exception {
        // todo 编码问题，window 环境下压缩文件是 GBK 编码，，liunx 环境下是 UTF-8,
        // todo 部署在liunx 环境下，要指定编码 zipFile = new ZipFile(fileZip, Charset.forName("GBK"));
        ZipFile zipFile = new ZipFile(fileZip);
        if (!fileDirectory.exists() && fileDirectory.mkdir()) {
            System.out.println(String.format("创建%s目录成功!",fileDirectory.getAbsolutePath()));
        }
        zipFile.stream().forEach(item -> {
            System.out.println(String.format("解压了%s文件...", item.getName()));
            String fileName = item.getName();
            if (fileName.contains(File.separator)) {
                // 最后一个分隔符的位置
                int index = fileName.lastIndexOf(File.separator);
                File tempDirectory = new File(fileDirectory.getAbsolutePath() + File.separator + fileName.substring(0, index));
                if (!tempDirectory.exists() && tempDirectory.mkdir()) {
                    System.out.println(String.format("创建%s目录成功!",tempDirectory.getAbsolutePath()));
                }
            }
            try {
                InputStream inputStream = zipFile.getInputStream(item);
                Files.copy(inputStream, Paths.get(fileDirectory.getAbsolutePath() + File.separator, fileName));
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}